package main

import (
	"ecld.com/prowatcher/pb"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"golang.org/x/net/context"
	"sync"
)

type authServer struct {
	handler Handler
}

var (
	mp sync.RWMutex // guards passed
	mt sync.RWMutex // guards token
)

func NewAuthServer() *authServer {
	handler := NewAuthHandler()
	logger.Println("Build Auth Server")
	return &authServer{handler}
}

func (a *authServer) Auth(ctx context.Context, in *pb.AuthRequest) (*pb.AuthResponse, error) {

	logger.Printf("-> auth request from user %v", in.Uname)
	ffmt := fmt.Sprint("<- auth unsuccess, cause by %v")
	mp.RLock()
	err := a.handler.Login(in.Uname, in.Passwd)
	mp.RUnlock()
	if err != nil {
		logger.Printf(ffmt, err)
		return &pb.AuthResponse{Err: err.Error()}, nil
	}
	mt.Lock()
	token, vaildUntil, err := a.handler.TouchToken(in.Uname)
	mt.Unlock()
	if err != nil {
		logger.Printf(ffmt, err)
		return &pb.AuthResponse{Err: err.Error()}, nil
	}
	logger.Println("<- auth success")
	return &pb.AuthResponse{Token: &token, ValidUntil: vaildUntil}, nil

}

func (a *authServer) AuthToken(ctx context.Context, in *pb.AuthTokenRequest) (*pb.AuthTokenResponse, error) {

	logger.Printf("-> authtoken request for resource = %v from user %v", in.ResourcePath, in.Token.User)
	ffmt := fmt.Sprint("<- authtoken unsuccess, cause by %v")
	mt.RLock()
	vaildUntil, err := a.handler.LoginByToken(in.Token.User, in.Token.Token)
	mt.RUnlock()
	if err != nil {
		logger.Printf(ffmt, err)
		return &pb.AuthTokenResponse{Valid: false, Err: err.Error()}, nil
	}
	err = a.handler.TouchPermission(in.Token.User, in.ResourcePath)
	if err != nil {
		logger.Printf(ffmt, err)
		return &pb.AuthTokenResponse{Valid: false, Err: err.Error()}, nil
	}
	logger.Printf("<- authtoken success")
	return &pb.AuthTokenResponse{Valid: true, ValidUntil: vaildUntil}, nil

}

func (a *authServer) ChangePass(ctx context.Context, in *pb.ChangePassRequest) (*pb.ChangePassResponse, error) {

	logger.Printf("-> changepass request from user %v", in.Uname)
	ffmt := fmt.Sprint("<- changepass unsuccess, cause by %v")
	mp.Lock()
	defer mp.Unlock()
	err := a.handler.Login(in.Uname, in.Passwd)
	if err != nil {
		logger.Printf(ffmt, err)
		return &pb.ChangePassResponse{Err: err.Error()}, nil
	}
	err = a.handler.UpdateInfo(in.Uname, in.NewPasswd)
	if err != nil {
		logger.Printf(ffmt, err)
		return &pb.ChangePassResponse{Err: err.Error()}, nil
	}
	logger.Printf("<- changepass success")
	return &pb.ChangePassResponse{}, nil

}
